package com.google.code.androiddatasender;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Net {

    private ReceiveCallback callback = null;
    private Configuration conf = null;
    private Socket sck = null;
    private ServerSocket svr = null;
    private DataOutputStream dos = null;
    private Receiver receiver = null;
    private boolean running = true;
    private ArrayList<Receiver> receiverList = null;

    public Net() {
    }

    public void initialize(Configuration conf) {
        this.conf = conf;
        if (conf.transport == Configuration.TRANSPORT_TCP) {
            if (conf.mode == Configuration.MODE_SENDER) {
                try {
                    sck = new Socket(conf.ip, conf.port);
                    dos = new DataOutputStream(sck.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else if (conf.mode == Configuration.MODE_RECEIVER) {
                try {
                    receiverList = new ArrayList<Receiver>();
                    svr = new ServerSocket();
                    svr.bind(new InetSocketAddress(conf.ip, conf.port));            
                } catch (IOException ioe) {
                }
            }
        } else {

        }
    }

    public void start() {
        if (conf.mode == Configuration.MODE_SENDER) {
            if (this.callback != null) {
                receiver = new Receiver(sck, this.callback);
                receiver.start();
            }
        }
    }

    public void loop() {
        if (conf.mode == Configuration.MODE_SENDER) {
            while (running) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ire) {
                }
            }
        } else if (conf.mode == Configuration.MODE_RECEIVER) {
            while (running) {
                try {
                    Socket sck = svr.accept();
                    this.sck = sck;
                    if (this.callback != null) {
                        receiver = new Receiver(sck, this.callback);
                        receiver.start();
                        receiverList.add(receiver);
                    }
                } catch (IOException ioe) {

                }
            }
        }
    }

    public void shutdown() {
        try {
            running = false;

            if (receiver != null)
                receiver.shutdown();

            while (receiverList.size() > 0) {
                Receiver receiver = receiverList.get(0);
                receiverList.remove(0);
                receiver.shutdown();
            }

            if (sck != null)
                sck.close();
            if (svr != null)
            	svr.close();
        } catch (IOException e) {
        }
    }

    public ArrayList<Receiver> getReceiverList() {
        return receiverList;
    }

    public void send(Msg msg) {
    	if (conf.mode == Configuration.MODE_SENDER) {
	        try {
	            byte[] buffer = msg.packet.toByteArray();           
	            dos.write(buffer, 0, buffer.length);
	            dos.flush();
	        } catch (IOException e) {
	        }
    	} else if (conf.mode == Configuration.MODE_RECEIVER) { // BroadCast
    		for (Receiver receiver : receiverList) {
    			receiver.send(msg);
    		}
    	}
    }

    public void receiveCallback(ReceiveCallback callback) {
        this.callback = callback;
    }
}
